/**
 * 有一个长度为 arrLen 的数组，开始有一个指针在索引 0 处。
 * <p>
 * 每一步操作中，你可以将指针向左或向右移动 1 步，或者停在原地（指针不能被移动到数组范围外）。
 * <p>
 * 给你两个整数 steps 和 arrLen ，请你计算并返回：在恰好执行 steps 次操作以后，指针仍然指向索引 0 处的方案数。
 * <p>
 * 由于答案可能会很大，请返回方案数 模 10^9 + 7 后的结果。
 * <p>
 *  
 * <p>
 * 示例 1：
 * <p>
 * 输入：steps = 3, arrLen = 2
 * 输出：4
 * 解释：3 步后，总共有 4 种不同的方法可以停在索引 0 处。
 * 向右，向左，不动
 * 不动，向右，向左
 * 向右，不动，向左
 * 不动，不动，不动
 * 示例  2：
 * <p>
 * 输入：steps = 2, arrLen = 4
 * 输出：2
 * 解释：2 步后，总共有 2 种不同的方法可以停在索引 0 处。
 * 向右，向左
 * 不动，不动
 * 示例 3：
 * <p>
 * 输入：steps = 4, arrLen = 2
 * 输出：8
 *  
 * <p>
 * 提示：
 * <p>
 * 1 <= steps <= 500
 * 1 <= arrLen <= 10^6
 */
class Solution {

    public static void main(String[] args) {
       /* System.out.println(numWays(1, 3));
        System.out.println(numWays(2, 3));
        System.out.println(numWays(3, 3));
        System.out.println(numWays(4, 3));
        System.out.println(numWays(5, 3));*/
        System.out.println(numWays(3, 2));
        System.out.println(numWays(2, 4));
        System.out.println(numWays(4, 2));
    }

    private static int posMax;
    private static int[][] dp;

    /**
     * 先尝试用最简单递归来做，结果肯定超时，其中存在大量重复计算
     *
     * @param steps
     * @param arrLen
     * @return
     */
    public static int numWays(int steps, int arrLen) {
        if (arrLen > 4) {
            arrLen = Math.min(arrLen, steps / 2);
        }
        posMax = arrLen - 1;
        dp = new int[steps + 1][arrLen];
        return loop(steps, 0);
    }

    public static int loop(int steps, int pos) {
        if (steps == 0) {
            return pos == 0 ? 1 : 0;
        }
        if (dp[steps][pos] != 0) {
            return dp[steps][pos];
        }
        int count = 0;
        // 不动
        count += loop(steps - 1, pos);
        if (pos > 0) {
            count += loop(steps - 1, pos - 1);
        }
        if (pos < posMax) {
            count += loop(steps - 1, pos + 1);
        }
        if (count >= 1000000007) {
            count %= 1000000007;
        }
        dp[steps][pos] = count;
        return count;
    }
}